﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
// custom headers
#include "IEditingProjectComponent.h"
#include "ISpecification.h"
#include "IParameter.gcs.h"
#include "IParameterDefinition.gcs.h"
#include "ILegend.h"
#include "DebugMessage.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 



namespace gmepgcs
{
    IEditingProjectComponent::IEditingProjectComponent() :
        Id(),
        PublicComponentId(),
        Version(),
        Name(),
        CategoryCode(),
        ParameterDefinitions(),
        Specifications(),
        Legends()
    {
    }

    IEditingProjectComponent::~IEditingProjectComponent()
    {
    }

    bool IEditingProjectComponent::operator==(const IEditingProjectComponent & other)
    {
        // compare id
        if (Id != other.Id)
        {
            return false;
        }
        // compare public Compid
        if (PublicComponentId != other.PublicComponentId)
        {
            return false;
        }
        // compare public source version
        if (PublicSourceVersion != other.PublicSourceVersion)
        {
            return false;
        }

        // compare version
        if (Version != other.Version)
        {
            return false;
        }

        // compare name
        if (Name != other.Name)
        {
            return false;
        }

        // compare category
        if (CategoryCode != other.CategoryCode)
        {
            return false;
        }

        // compare parameter definitions
        if (ParameterDefinitions.size() != other.ParameterDefinitions.size())
        {
            return false;
        }

        for (auto &thisParamDefPair : ParameterDefinitions)
        {
            auto otherParamDefPairIterator = other.ParameterDefinitions.find(thisParamDefPair.first);
            if (otherParamDefPairIterator == other.ParameterDefinitions.end())
            {
                return false;
            }

            if ((nullptr == thisParamDefPair.second) && (nullptr == otherParamDefPairIterator->second))
            {
                continue;
            }
            else if ((nullptr != thisParamDefPair.second) && (nullptr != otherParamDefPairIterator->second))
            {
                if (*(thisParamDefPair.second) != *(otherParamDefPairIterator->second))
                {
                    return false;
                }
                else
                {
                    continue;
                }
            }
            else
            {
                return false;
            }
        }

        // compare specifications
        if (Specifications.size() != other.Specifications.size())
        {
            return false;
        }

        for (auto &thisSpecPair : Specifications)
        {
            auto otherSpecPairIterator = other.Specifications.find(thisSpecPair.first);
            if (otherSpecPairIterator == other.Specifications.end())
            {
                return false;
            }

            if ((nullptr == thisSpecPair.second) && (nullptr == otherSpecPairIterator->second))
            {
                continue;
            }
            else if ((nullptr != thisSpecPair.second) && (nullptr != otherSpecPairIterator->second))
            {
                if (*(thisSpecPair.second) != *(otherSpecPairIterator->second))
                {
                    return false;
                }
                else
                {
                    continue;
                }
            }
            else
            {
                return false;
            }
        }

        // compare legends
        if (Legends.size() != other.Legends.size())
        {
            return false;
        }

        for (auto &thisLegendPair : Legends)
        {
            auto otherLegendPairIterator = other.Legends.find(thisLegendPair.first);
            if (otherLegendPairIterator == other.Legends.end())
            {
                return false;
            }

            if ((nullptr == thisLegendPair.second) && (nullptr == otherLegendPairIterator->second))
            {
                continue;
            }
            else if ((nullptr != thisLegendPair.second) && (nullptr != otherLegendPairIterator->second))
            {
                if (*(thisLegendPair.second) != *(otherLegendPairIterator->second))
                {
                    return false;
                }
                else
                {
                    continue;
                }
            }
            else
            {
                return false;
            }
        }

        return true;
    }

    bool IEditingProjectComponent::operator!=(const IEditingProjectComponent & other)
    {
        return !operator==(other);
    }

    std::shared_ptr<IEditingProjectComponent> IEditingProjectComponent::Clone()
    {
        std::shared_ptr<IEditingProjectComponent> spClone = std::make_shared<IEditingProjectComponent>();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(spClone, L"spClone 为空", L"GMEP", L"2024-01-30");       
        spClone->Id = Id;
        spClone->PublicComponentId = PublicComponentId;
        spClone->PublicSourceVersion = PublicSourceVersion;
        spClone->Version = Version;
        spClone->Name = Name;
        spClone->CategoryCode = CategoryCode;
        spClone->CategoryGuid = CategoryGuid;
        
        // clone parameter definitions
        spClone->ParameterDefinitions = std::map<std::wstring, std::shared_ptr<IParameterDefinition>>();
        for (auto &originParamDefPair : ParameterDefinitions)
        {
            spClone->ParameterDefinitions[originParamDefPair.first] = 
                nullptr == originParamDefPair.second
                ? nullptr 
                : originParamDefPair.second->Clone();
        }

        // clone specifications
        spClone->Specifications = std::map<std::wstring, std::shared_ptr<ISpecification>>();
        for (auto &originSpecPair : Specifications)
        {
            spClone->Specifications[originSpecPair.first] =
                nullptr == originSpecPair.second
                ? nullptr 
                : originSpecPair.second->CloneWithExternalParameterDefinition(spClone->ParameterDefinitions);
        }

        // clone legends
        spClone->Legends = std::map<ILegend::LegendType, std::shared_ptr<ILegend>>();
        for (auto &originLegendPair : Legends)
        {
            spClone->Legends[originLegendPair.first] =
                nullptr == originLegendPair.second
                ? nullptr
                : originLegendPair.second->Clone();
        }

        return spClone;
    }
}